package com.zsp.coupon.executor;


import com.zsp.coupon.constant.CouponCategory;
import com.zsp.coupon.constant.RuleFlag;
import com.zsp.coupon.exception.CouponException;
import com.zsp.coupon.vo.SettlementInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 优惠卷规则结算执行器
 * 根据用户的请求找到对应的 Excutor去做结算
 * * 即根据用户的请求(SettlementInfo)找到对应的 Executor, 去做结算
 *  * BeanPostProcessor: Bean 后置处理器
 */
@Component
@Slf4j
public class ExceutorManger  implements BeanPostProcessor {

    /** 规则执行器映射 */
private static Map<RuleFlag,RuleExecutor> executorindex =
        new HashMap<>(RuleFlag.values().length);


    /**
     * <h2>优惠券结算规则计算入口</h2>
     * 注意: 一定要保证传递进来的优惠券个数 >= 1
     * */

    public SettlementInfo computeRule(SettlementInfo settlement)
            throws CouponException {
                  SettlementInfo result = null;
                  //当类优惠卷
                    if (settlement.getCouponAndTemplateInfo().size() == 1) {
                        //获取优惠卷的类别
                        CouponCategory category = CouponCategory.of(
                                settlement.getCouponAndTemplateInfo().get(0)
                                        .getTemplate().getCategory());

                        switch (category) {
                            case MANNJIAN:
                                result = executorindex.get(RuleFlag.MANJIAN)
                                        .computeRule(settlement);
                                break;
                            case ZHEKOU:
                                result = executorindex.get(RuleFlag.ZHEKOU)
                                        .computeRule(settlement);
                                break;
                            case LIJIAN:
                                result = executorindex.get(RuleFlag.LIJIAN)
                                        .computeRule(settlement);
                                break;

                        }
                    }else {
                        //多类优惠卷
                        List<CouponCategory> categories = new ArrayList<>(
                                settlement.getCouponAndTemplateInfo().size()
                        );
                        settlement.getCouponAndTemplateInfo()
                                .forEach(ct -> categories.add(CouponCategory.of(
                                        ct.getTemplate().getCategory()
                                )));

                        if (categories.size() !=2) {
                            throw new CouponException("not Support  for more template category");
                        } else {
                            if (categories.contains(CouponCategory.MANNJIAN) &&
                             categories.contains(CouponCategory.ZHEKOU)) {
                                result = executorindex.get(RuleFlag.MANJIAN_ZHEKOU)
                                        .computeRule(settlement);
                            }
                            else {
                                throw  new CouponException("not support for other" +
                                        "template Category");
                            }
                        }

                    }
                    return  result;
    }



    /**
     * <h2>在 bean 初始化之前去执行(before)</h2>
     * */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (!(bean instanceof RuleExecutor)) {
                    return bean;
                }

                RuleExecutor executor =(RuleExecutor) bean;
                  RuleFlag ruleFlag = executor.ruleConfig();
                  if (executorindex .containsKey(ruleFlag)) {
                      throw new IllegalStateException("There is already an executor" +
                              "for rule flag: " + ruleFlag);
                  }

        log.info("Load executor {} for rule flag {}.",
                executor.getClass(), ruleFlag);
        executorindex.put(ruleFlag, executor);

        return null;
    }


    /**
     * <h2>在 bean 初始化之后去执行(after)</h2>
     * */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
